package main

import (
	"context"
	"github.com/gin-gonic/gin"
	"github.com/opentracing/opentracing-go"
	"github.com/opentracing/opentracing-go/ext"
	"github.com/opentracing/opentracing-go/log"
	zipkinot "github.com/openzipkin-contrib/zipkin-go-opentracing"
	//"io/ioutil"
	"golang.org/x/sync/errgroup"
	"net/http"
	"opentracing-study/common"
)

const (
	url = "http://127.0.0.1:8000/api/v1/user/info"
)

func main() {
	// init zipkin
	trace, err := common.NewZipkin(common.ClientAppID, "172.16.0.2:8000")
	if err != nil {
		panic(err)
	}
	opentracing.SetGlobalTracer(zipkinot.Wrap(trace))

	r := gin.Default()
	r.Use(common.Trace())
	r.GET("/login", func(ctx *gin.Context) {
		// get trace ctx
		var (
			trCtx context.Context
			ok    bool
		)
		if trCtx, ok = ctx.Value(common.TraceCtx).(context.Context); !ok {
			ctx.String(500, "没有找到上下文")
			return
		}
		// 测试并发调用
		g, _ := errgroup.WithContext(trCtx)

		for i := 0; i <= 10; i++ {
			g.Go(func() error {
				_, e := httpReq(trCtx)
				return e
			})
		}

		if err := g.Wait(); err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{
				"code":    -1,
				"message": err.Error(),
			})
			return
		}
		// http req
		//resp, err := httpReq(trCtx)
		//if err != nil {
		//	ctx.JSON(http.StatusInternalServerError, gin.H{
		//		"code":    -1,
		//		"message": err.Error(),
		//	})
		//	return
		//}
		//body, _ := ioutil.ReadAll(resp.Body)
		//ctx.JSON(http.StatusOK, gin.H{
		//	"code":    0,
		//	"message": "ok",
		//	"data":    body,
		//})
	})

	if err := r.Run("0.0.0.0:8080"); err != nil {
		panic(err)
	}
}

func httpReq(ctx context.Context) (resp *http.Response, err error) {
	span, _ := opentracing.StartSpanFromContext(ctx, "HTTP:GET")
	defer func() {
		if err != nil {
			// add error event
			ext.Error.Set(span, true)
			span.LogFields(
				log.String("event", "error"),
				log.String("message", err.Error()),
			)
		}
		span.Finish()
	}()
	client := &http.Client{}
	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return
	}
	ext.Component.Set(span, "net/http")
	ext.SpanKind.Set(span, "client")
	ext.HTTPMethod.Set(span, req.Method)
	ext.HTTPUrl.Set(span, req.URL.String())
	// 将trace注入http
	carrier := opentracing.HTTPHeadersCarrier(req.Header)
	opentracing.GlobalTracer().Inject(span.Context(), opentracing.HTTPHeaders, carrier)

	// req do
	resp, err = client.Do(req)
	return
}
